package com.flute.framework.util.ftp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;

import com.flute.framework.search.ProviderInfo;

public class FtpFile implements IFileOperation {
	private FtpConfig ftpConfig;
	FtpServer ftpServer;
	public static final String SPLIT_FLAG = "/";
	public static final String DEFAULT_PROTOCOL = "ftp";

	public FtpFile(FtpConfig config) {
		this.ftpConfig = config;
		ftpServer = new FtpServer();
	}

	@Override
	public String combin(String uri, String fileName) {
		if (uri == null || uri.trim().length() <= 0)
			throw new IllegalArgumentException("uri=" + uri);
		if (fileName == null || fileName.trim().length() <= 0)
			throw new IllegalArgumentException("fileName=" + fileName);
		StringBuilder result = new StringBuilder(uri);
		result.append(uri.endsWith(getSeparator()) ? "" : getSeparator());
		int splitLastPos = fileName.lastIndexOf(getSeparator());
		result.append(fileName.substring(splitLastPos + 1));
		return result.toString();
	}

	@Override
	public boolean createNewFile(String uri) throws Exception {
		return ftpServer.createNewFile(uri);
	}

	@Override
	public long size(String uri) throws Exception {
		return ftpServer.size(uri);
	}

	@Override
	public boolean delete(String uri) throws Exception {
		return ftpServer.deleteFile(uri);
	}

	@Override
	public boolean download(String uri, String filename) throws Exception {
		File targe = new File(filename);
		boolean result = true;
		if (targe.isDirectory() && isFile(uri)) {
			targe = new File(targe.getAbsolutePath()
					+ System.getProperty("file.separator") + uri);
		}
		if (exists(uri)) {
			if (isFile(uri)) {
				result = ftpServer.download(uri, targe.getAbsolutePath());
			} else {
				if (!targe.exists()) {
					result = targe.mkdirs();
				}
				if (result) {
					if (targe.isDirectory()) {
						String[] files = list(uri);
						for (String f : files) {
							ftpServer.changeDirectory(uri);
							try {
								result &= download(f, targe.getAbsolutePath()
										+ System.getProperty("file.separator")
										+ f);
							} finally {
								ftpServer.back();
							}
						}
					} else {
						result = false;
					}
				}
			}
		}
		return result;
	}

	@Override
	public boolean exists(String uri) throws Exception {
		return ftpServer.exists(uri);
	}

	@Override
	public void finalise() throws Exception {
		ftpServer.closeServer();
	}

	@Override
	public void init() throws Exception {
		ftpServer.connectServer(ftpConfig);
	}

	@Override
	public boolean isDirectory(String uri) throws Exception {
		return ftpServer.isDir(uri);
	}

	@Override
	public boolean isFile(String uri) throws Exception {
		return ftpServer.isFile(uri);
	}

	@Override
	public String[] list(String uri) throws Exception {
		return ftpServer.getFileList(uri).toArray(new String[0]);
	}

	@Override
	public InputStream load(String uri) throws Exception {
		return ftpServer.downFile(uri);
	}

	@Override
	public boolean mkdir(String uri) throws Exception {
		return ftpServer.createDir(uri);
	}

	@Override
	public boolean mkdirs(String uri) throws Exception {
		uri = uri.startsWith(getSeparator()) ? uri.substring(1) : uri;
		String[] paths = uri.split(getSeparator());
		int count = 0;
		try {
			for (String path : paths) {
				if (!ftpServer.isDir(path)) {
					if (!ftpServer.createDir(path)) {
						return false;
					}
				}
				ftpServer.changeDirectory(path);
				count++;
			}
			return true;
		} finally {
			ftpServer.back(count);
		}
	}

	@Override
	public boolean save(String uri, InputStream is) throws Exception {
		return ftpServer.uploadFile(is, uri);
	}

	@Override
	public boolean upload(String filename, String uri) throws Exception {
		File source = new File(filename);
		String targe = uri.trim();
		boolean result = true;
		int level = 0;
		if (isDirectory(targe)) {
			ftpServer.changeDirectory(targe);
			level++;
			targe = source.getName();
		}
		if (targe.length() <= 0) {
			targe = source.getName();
		}
		try {
			if (source.exists()) {
				if (source.isFile()) {
					result = ftpServer.uploadFile(source.getAbsolutePath(),
							targe);
				} else {
					if (!exists(targe)) {
						result = mkdir(targe);
					}
					if (result) {
						if (isDirectory(targe)) {
							ftpServer.changeDirectory(targe);
							level++;
							File[] files = source.listFiles();
							for (File file : files) {
								result &= upload(file.getAbsolutePath(), file
										.getName());
							}
						} else {
							result = false;
						}
					}
				}
			}
		} finally {
			ftpServer.back(level);
		}
		return result;
	}

	@Override
	public boolean createNewFile(String uri, String name) throws Exception {
		boolean result = false;
		String absolu = combin(uri, name);
		String[] splis = absolu.startsWith("/") ? absolu.substring(1)
				.split("/") : absolu.split("/");
		ftpServer.changeDirectory(splis, splis.length - 1);
		try {
			result = createNewFile(splis[splis.length - 1]);
		} finally {
			ftpServer.back(splis.length - 1);
		}
		return result;
	}

	@Override
	public boolean delete(String uri, String file) throws Exception {
		String absolu = combin(uri, file);
		String[] splis = absolu.startsWith("/") ? absolu.substring(1)
				.split("/") : absolu.split("/");
		ftpServer.changeDirectory(splis, splis.length - 1);
		boolean result = false;
		try {
			result = delete(splis[splis.length - 1]);
		} finally {
			ftpServer.back(splis.length - 1);
		}
		return result;
	}

	@Override
	public boolean removeDirectory(String uri) throws Exception {
		return ftpServer.removeDirectory(uri, true);
	}

	@Override
	public long lastModified(String uri) throws IOException {
		return ftpServer.lastModified(uri);
	}

	@Override
	public long getNotLockLastModifiedTime(String uri) {
		long lastmodified = -1;
		try {
			String[] files = list(uri);
			ftpServer.changeDirectory(uri);
			if (files != null) {
				for (int i = 0; i < files.length; i++) {
					long last = lastModified(files[i]);
					if (!files[i].endsWith(".lock") && lastmodified < last) {
						lastmodified = last;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				ftpServer.back();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			String[] files = list(uri);
			System.out.println(files.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return lastmodified;
	}

	@Override
	public String getSeparator() {
		return SPLIT_FLAG;
	}

	@Override
	public boolean clearFolder(String path, String name) {
		try {
			if (!isDirectory(path)) {
				return true;
			}
			String[] filelist = list(path);
			ftpServer.changeDirectory(path);
			if (filelist != null)
				for (int i = 0; i < filelist.length; i++) {
					if (isFile(filelist[i])) {
						if (filelist[i].equals(name)) {
							continue;
						} else {
							if (!delete(filelist[i])) {
								return false;
							}
						}
					} else {
						if (!removeDirectory(filelist[i])) {
							return false;
						}
					}
				}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				ftpServer.back();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static IFileOperation parse(ProviderInfo info) throws Exception {
		if (info != null) {
			FtpConfig ftpConfig = FtpConfig.parse(info);
			FtpFile ftpFile = new FtpFile(ftpConfig);
			ftpFile.init();
			FileOperationHandler h = new FileOperationHandler(ftpFile);
			return h.getPorxyInstance(ftpFile);
		} else {
			return null;
		}
	}

	public static void main(String[] args) throws Exception {
		FtpConfig config = new FtpConfig("192.168.1.104", 21, "ftp", "ftp", "pub",
				"utf8", FTP.ASCII_FILE_TYPE);
		FtpFile ftpFile = new FtpFile(config);
		ftpFile.init();
		FileOperationHandler h = new FileOperationHandler(ftpFile);
		IFileOperation file = h.getPorxyInstance(ftpFile);
		System.out.println(file.exists("/song/ready"));
		// String[] files = file.list("/basesongb");
		// for (String f : files) {
		// System.out.println(f);
		// }
		// System.out.println(file.getNotLockLastModifiedTime("/basesongb"));
	}
}
